package com.wlz.nio;

import lombok.With;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author wlz
 * @date 2022-07-06  9:27 下午
 */
@Slf4j
public class MyNioServer {

    static List<SocketChannel> channels = new ArrayList<>();

    public static void main(String[] args) throws Exception{

        // 创建 nio serverSocketChannel， 与 bio serverSocket 类似
        ServerSocketChannel serverSocket =ServerSocketChannel.open();
        // 绑定端口
        serverSocket.socket().bind(new InetSocketAddress(9000));

        // 设置 ServerSocketChannel 为 非阻塞
        serverSocket.configureBlocking(false);

        log.info("服务端启动成功......");

        while (true) {
            // 非阻塞 模式 accept 方法不会阻塞，否则会阻塞
            // nio 的非阻塞 是由 底层操作系统内部实现的，底层调用了linux 内核的 accept 函数
            SocketChannel socketChannel = serverSocket.accept();
            if (null != socketChannel) {
                log.info(" 连接成功 。。。。");
                // 设置 SocketChannel 为非阻塞
                socketChannel.configureBlocking(false);
                // 保存客户端连接在list 中
                channels.add(socketChannel);
            }

            Iterator<SocketChannel> iterator = channels.iterator();
            while (iterator.hasNext()) {
                SocketChannel sc = iterator.next();
                ByteBuffer byteBuffer = ByteBuffer.allocate(128);

                // 非阻塞 模式 read 方法不会阻塞，否则会阻塞
                int len = sc.read(byteBuffer);
                if (len > 0) {
                    log.info("接收到消息: {}", new String(byteBuffer.array()));
                }else if (len == -1 ) { // 如果客户端断开，把socket 从集合中去除
                    iterator.remove();
                    log.info("客户端断开连接 。。。。。");
                }
            }

        }

    }
}
